﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace WcfServer.Classes.Utility
{
    public class EncryptionHandler
    {

        public static int RSAKeyLength = 4096;
        /* Begin Encrypt Methods */

            public static byte[] EncryptRSA(byte[] data, RSAParameters KeyInfo)
            {
                RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(RSAKeyLength);
                RSA.ImportParameters(KeyInfo);
                return RSA.Encrypt(data, false);
            }
        
            public static byte[] EncryptRSA(byte[] data, String ContainerName)
            {
                CspParameters cp = new CspParameters();
                cp.KeyContainerName = ContainerName;

                //If finds a ContainerName available already uses it. Otherwise, creates new.
                RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(RSAKeyLength,cp);
                return rsa.Encrypt(data, false);
            }

            public static byte[] EncryptRSA_XML(byte[] data, String Xml)
            {
                RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(RSAKeyLength);
                RSA.FromXmlString(Xml);
                return RSA.Encrypt(data, false);
            }

        /* Begin Decrypt Methods */

            public static byte[] DecryptRSA(byte[] data, RSAParameters KeyInfo)
            {
                RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(RSAKeyLength);
                RSA.ImportParameters(KeyInfo);
                return RSA.Decrypt(data, false);
            }

            //Caution: This might malfunction if used to decrypt data using a name not available.
            public static byte[] DecryptRSA(byte[] data, String ContainerName)
            {
                
                CspParameters cp = new CspParameters();
                cp.KeyContainerName = ContainerName;

                //If finds a ContainerName available already uses it. Otherwise, creates new.
                RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(RSAKeyLength, cp);
                return rsa.Decrypt(data, false);
            }

            public static byte[] DecryptRSA_XML(byte[] data, String Xml)
            {
                RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(RSAKeyLength);
                RSA.FromXmlString(Xml);
                return RSA.Decrypt(data, false);
            }





        /* Begin AES Encryption */
            public static byte[] EncryptAES(byte[] data, byte[] key)
            {
                using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
                {
                    aesAlg.Key = key;
                    aesAlg.IV = new byte[16];

                    // Create a decrytor to perform the stream transform.
                    ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

                    var res = encryptor.TransformFinalBlock(data, 0, data.Length);
                    return res;

                    // Create the streams used for encryption. 
                    //using (MemoryStream msEncrypt = new MemoryStream())
                    //{
                    //    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    //    {
                    //        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                    //        {
                    //            //Write all data to the stream.
                    //            swEncrypt.Write(data);
                    //        }
                    //        return msEncrypt.ToArray();
                    //    }
                    //}
                }
            }
        
        /* Begin AES Decryption */
            public static byte[] DecryptAES(byte[] data, byte[] key)
            {
                using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
                {
                    aesAlg.Key = key;
                    aesAlg.IV = new byte[16];
                   // string decipher = "";
                    // Create a decrytor to perform the stream transform.
                    ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
                    var res = decryptor.TransformFinalBlock(data, 0, data.Length);
                    return res;
                    // Create the streams used for encryption. 
                    //using (MemoryStream msEncrypt = new MemoryStream(data))
                    //{
                    //    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, decryptor, CryptoStreamMode.Read))
                    //    {
                    //        using (StreamReader swEncrypt = new StreamReader(csEncrypt))
                    //        {
                    //            //Write all data to the stream.
                    //            decipher = swEncrypt.ReadToEnd();
                    //        }
                    //        return Encoding.UTF8.GetBytes(decipher);
                    //    }
                    //}
                }
            }
        
        /* Begin Hash Functions */
            public static byte[] HashSHA256(byte[] data)
            {
                SHA256CryptoServiceProvider sha = new SHA256CryptoServiceProvider();
                return sha.ComputeHash(data);
            }
    }
}
